package com.cf.user.permission.filter;

import cn.hutool.core.collection.CollectionUtil;
import com.cf.constant.EnumReturnCode;
import com.cf.order.Ordered;
import com.cf.user.login.model.UserInfo;
import com.cf.user.login.service.TokenManager;
import com.cf.user.permission.model.SystemPermission;
import com.cf.user.permission.service.SystemPermissionService;
import com.cf.util.RequestUtil;
import com.cf.vo.ResponseVo;
import com.cf.web.RequiredPermission;
import com.cf.web.autoconfigure.WebCommonProperty;
import com.cf.web.controller.MvcHandlers;
import com.cf.web.filter.ZmmFilter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * game-server-PermissionHandlerInterceptor
 * 权限验证filter，主要解决部分url无法管控的问题
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/6/13 下午 01:20
 */
@Slf4j
public class PermissionFilter extends ZmmFilter implements Ordered {


    public PermissionFilter() {
        log.info("实例化权限检测过滤器");
    }

    @Autowired
    private MvcHandlers mvcHandlers;

    @Autowired
    private TokenManager tokenManager;

    @Autowired
    private WebCommonProperty webCommonProperty;

    @Autowired
    private SystemPermissionService permissionService;

    /**
     * 是否有权限
     *
     * @param request
     * @param handler
     * @return
     */
    private boolean hasPermission(HttpServletRequest request, Object handler) {
        if (!needPermission(handler, request))
            return true;

        RequiredPermission requiredPermission = getRequiredPermission(handler);

        if (requiredPermission == null)
            return true;

        // redis或数据库 中获取该用户的权限信息 并判断是否有权限
        Set<String> permissionSet = getUserPermission(request);
        if (CollectionUtil.isEmpty(permissionSet)) {
            return false;
        } else {
            return permissionSet.contains(requiredPermission.value());
        }
    }

    private RequiredPermission getRequiredPermission(Object handler) {

        if (handler == null) {
            return null;
        }

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取方法上的注解
            RequiredPermission requiredPermission = handlerMethod.getMethod().getAnnotation(RequiredPermission.class);
            // 如果方法上的注解为空 则获取类的注解
            if (requiredPermission == null) {
                requiredPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequiredPermission.class);
            }
            return requiredPermission;
        } else {
            return null;
        }
    }

    private boolean needPermission(Object handler, HttpServletRequest request) {

        if (handler == null) {
            log.info("当前未找到url对应的处理器，执行严格模式，需要进行权限验证" + RequestUtil.getIpAddr(request));
            return false;
        }

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取方法上的注解
            RequiredPermission requiredPermission = handlerMethod.getMethod().getAnnotation(RequiredPermission.class);
            // 如果方法上的注解为空 则获取类的注解
            if (requiredPermission == null) {
                requiredPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequiredPermission.class);
            }
            // 如果标记了注解，则判断权限
            if (requiredPermission != null && StringUtils.isNotBlank(requiredPermission.value())) {
                return true;
            } else {
                return false;
            }
        }
        return true;
    }

    private Set<String> getUserPermission(HttpServletRequest request) {
        UserInfo userInfo = tokenManager.userInfo(request);
        if (userInfo == null)
            return new HashSet();
        List<SystemPermission> permissionList = permissionService.userPermission(userInfo.getId());
        if (permissionList == null || permissionList.size() == 0)
            return new HashSet();

        return permissionList.stream().map(permission -> {
            return permission.getPermissionCode();
        }).collect(Collectors.toSet());

    }

    @Override
    public int getOrder() {
        return 20;
    }


    @Override
    protected void doInnerFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 验证权限
        if (this.hasPermission(request, mvcHandlers.handler(request))) {
            chain.doFilter(request, response);
            return;
        }
        if (mvcHandlers.isJsonResponse(request)) {
            RequestUtil.renderJson(response, ResponseVo.fail(EnumReturnCode.PERMISSION_ERROR.getCode(), null, "当前访问权限不足！"));
        } else {
            response.sendRedirect(webCommonProperty.getErrorPage() + "?msg=" + URLEncoder.encode("权限不足，无法访问！", "utf-8"));
        }
    }


    @Override
    public List<String> matchPathPatterns() {
        return Arrays.asList("/*");
    }
}
